package com.swan.web.aop;

import com.alibaba.fastjson2.JSONObject;
import com.swan.web.auto.config.WebConfig;
import lombok.extern.slf4j.Slf4j;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.PriorityOrdered;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;

/** 日志处理: 打印请求参数和响应结果
 * @author zongf
 * @date 2024-02-04
 **/
@Slf4j
public class HttpLogAspect implements MethodInterceptor, PriorityOrdered {

    private WebConfig.HttpLogConfig httpLogConfig;

    private String serverContextPath;

    public HttpLogAspect(WebConfig httpLogConfig, String serverContextPath) {
        this.httpLogConfig = httpLogConfig.getHttpLog();
        this.serverContextPath = serverContextPath;
    }

    @Override
    public Object invoke(MethodInvocation methodInvocation) {

        long start = System.currentTimeMillis();

        // 获取请求地址
        String requestUri = getRequestUri();

        String requestJson = null;
        Object result = null;
        try {
            // 判断是否忽略
            if (httpLogConfig.getIgnoreUriPrefixes().contains(requestUri)) {
                return methodInvocation.proceed();
            }

            requestJson = getParamsJson(methodInvocation);
            log.info("[HTTP请求-开始] uri:{}, 请求参数:{}", requestUri, requestJson);
            // 调用目标方法
            result = methodInvocation.proceed();

            if (httpLogConfig.getLogResponse()) {
                String responseJson = result == null ? null : JSONObject.toJSONString(result);
                log.info("[HTTP请求-结束] uri:{}, 请求参数:{}, 响应参数:{}, 耗时:{} ms", requestUri, requestJson, responseJson, (System.currentTimeMillis() - start));
            } else {
                log.info("[HTTP请求-结束] uri:{}, 请求参数:{}, 耗时:{} ms", requestUri, requestJson, (System.currentTimeMillis() - start));
            }
        } catch (RuntimeException ex) {
            throw ex;
        } catch (Throwable ex) {
            log.error("[HTTP请求-异常] uri:{}, 请求参数:{}", requestUri, requestJson);
            throw new RuntimeException(ex);
        }
        return result;

    }

    private String getParamsJson(MethodInvocation methodInvocation){
        Method method = methodInvocation.getMethod();

        Parameter[] parameters = method.getParameters();
        if(parameters == null || parameters.length == 0){
            return null;
        }

        JSONObject paramJsonObj = new JSONObject();
        int i = 0;
        for (Parameter parameter : method.getParameters()) {
            paramJsonObj.put(parameter.getName(), methodInvocation.getArguments()[i++]);
        }
        return paramJsonObj.toJSONString();
    }

    private String getRequestUri() {
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        if (requestAttributes != null && requestAttributes instanceof ServletRequestAttributes) {
            // 获取请求的URI
            ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            String requestURI = servletRequestAttributes.getRequest().getRequestURI();
            if (StringUtils.hasText(serverContextPath) && requestURI.startsWith(serverContextPath)) {
                return requestURI.substring(serverContextPath.length());
            }
            return requestURI;
        }

        return null;
    }

    @Override
    public int getOrder() {
        return httpLogConfig.getInterceptorOrder();
    }
}
